package com.algorithm.ch1.cjm.string;

/**
 * 实现 atoi，将字符串转为整数。
 * <p>
 * 在找到第一个非空字符之前，需要移除掉字符串中的空格字符。如果第一个非空字符是正号或负号，选取该符号，并将其与后面尽可能多的连续的数字组合起来，这部分字符即为整数的值。如果第一个非空字符是数字，则直接将其与之后连续的数字字符组合起来，形成整数。
 * <p>
 * 字符串可以在形成整数的字符后面包括多余的字符，这些字符可以被忽略，它们对于函数没有影响。
 * <p>
 * 当字符串中的第一个非空字符序列不是个有效的整数；或字符串为空；或字符串仅包含空白字符时，则不进行转换。
 * <p>
 * 若函数不能执行有效的转换，返回 0。
 * <p>
 * 说明：
 * <p>
 * 假设我们的环境只能存储 32 位有符号整数，其数值范围是 [−231,  231 − 1]。如果数值超过可表示的范围，则返回  INT_MAX (231 − 1) 或 INT_MIN (−231) 。
 * <p>
 * 示例 1:
 * <p>
 * 输入: "42"
 * 输出: 42
 * 示例 2:
 * <p>
 * 输入: "   -42"
 * 输出: -42
 * 解释: 第一个非空白字符为 '-', 它是一个负号。
 * 我们尽可能将负号与后面所有连续出现的数字组合起来，最后得到 -42 。
 * 示例 3:
 * <p>
 * 输入: "4193 with words"
 * 输出: 4193
 * 解释: 转换截止于数字 '3' ，因为它的下一个字符不为数字。
 * 示例 4:
 * <p>
 * 输入: "words and 987"
 * 输出: 0
 * 解释: 第一个非空字符是 'w', 但它不是数字或正、负号。
 * 因此无法执行有效的转换。
 * 示例 5:
 * <p>
 * 输入: "-91283472332"
 * 输出: -2147483648
 * 解释: 数字 "-91283472332" 超过 32 位有符号整数范围。
 * 因此返回 INT_MIN (−231) 。
 */
public class MyAtoi {

    public static void main(String[] args) {
        int res = MyAtoi.myAtoi1("-abc");

        System.out.println(res);

//        System.out.println((int)(Math.pow(2, 31) - 1));
//        System.out.println((int)Math.pow(-2, 31));
    }

    /**
     * 第一版本
     * T(n) = n
     * f(n) = n
     * @param str
     * @return
     */
    public int myAtoi(String str) {

        if(isBlank(str)){
            return 0;
        }

        str = str.trim();

        char[] chars = str.toCharArray();

        char[] res = new char[chars.length];
        int length = 0;

        for (int i = 0; i < chars.length; i++) {

            if(chars[i] == '0' && (length == 0 || length == 1 && (chars[0] == '-' || chars[0] == '+'))){
                continue;
            }

            if(i == 0){
                if(!(chars[i] == '-' || chars[i] == '+' || chars[i] >= '0' && chars[i] <= '9')){
                    return 0;
                }

                res[length++] = chars[i];
            }else {

                if(chars[i] >= '0' && chars[i] <= '9'){
                    res[length++] = chars[i];
                }else {
                    break;
                }
            }
        }

        if(length == 0 || length == 1 && (res[0] == '-' || res[0] == '+')){
            return 0;
        }

        String resStr = new String(res).substring(0, length);

        if(resStr.length() > 11){

            if(res[0] == '-'){
                return Integer.MIN_VALUE;
            }else {
                return Integer.MAX_VALUE;
            }
        }

        Long a = Long.valueOf(resStr);

        if(a > Integer.MAX_VALUE){
            return Integer.MAX_VALUE;
        }else if(a < Integer.MIN_VALUE){
            return Integer.MIN_VALUE;
        }

        return a.intValue();
    }

    /**
     * 判断是否为空字符
     * @param str
     * @return
     */
    public static boolean isBlank(String str) {
        int strLen;
        if (str == null || (strLen = str.length()) == 0) {
            return true;
        }
        for (int i = 0; i < strLen; i++) {
            if ((Character.isWhitespace(str.charAt(i)) == false)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 第二版
     * 字符串转换为整数
     * 1.字符串首位第一个不为空的的整数
     * 2.连续的整数
     *
     * T(n) = n;
     * f(n) = n;
     * @param str
     * @return
     */
    public static int myAtoi1(String str){

        int length = str.length();

        //字符串索引
        int index = 0;
        boolean positive = true;

        while (index < length && str.charAt(index) == ' '){
            index ++;
        }
        if(index < length && str.charAt(index) == '+'){
            index ++;
        } else if (index < length && str.charAt(index) == '-'){
            index ++;
            positive = false;
        }

        int res = 0;
        int ch;
        while (index < length && Character.isDigit(str.charAt(index))){

            ch = str.charAt(index) - '0';

            if(positive){

                if(res > Integer.MAX_VALUE/10 || res == Integer.MAX_VALUE/10 && ch > Integer.MAX_VALUE%10){
                    return Integer.MAX_VALUE;
                }

                res = res * 10 + ch;
            }else {
                ch = -ch;

                if(res < Integer.MIN_VALUE/10 || res == Integer.MIN_VALUE/10 && ch < Integer.MIN_VALUE%10){
                    return Integer.MIN_VALUE;
                }

                res = res * 10 + ch;
            }
            index++;
        }

        return res;
    }




}
